# -*- coding: utf-8 -*-
import sys, os
import errno
import signal
import pwd
from time import sleep
from os.path import exists
from traceback import format_exc


def _checkAlive(pid):
    try:
        os.kill(pid, 0)
        return True
    except OSError, e:
        if e.errno == errno.ESRCH:
            return False
        else:
            return True


class Initd(object):
    def __init__(self, pidfile, workdir="."):
        self.pidfile = pidfile
        self.workdir = workdir
        self.running = True

    def setUser(self, user):
        try:
            uid = int(user)
        except ValueError:
            try:
                pwrec = pwd.getpwnam(user)
            except KeyError, e:
                raise Exception('username %r not found'%user)
            uid = pwrec.pw_uid
        else:
            try:
                pwrec = pwd.getpwuid(uid)
            except KeyError, e:
                raise Exception('uid %r not found'%user)
        euid = os.geteuid()
        if euid != 0 and euid != uid:
            raise Exception('only root can change users')
        os.setgid(pwrec.pw_gid)
        os.setuid(pwrec.pw_uid)

    @property
    def pid(self):
        try:
            f = open(self.pidfile)
            try:
                return int(f.read().strip())
            finally:
                f.close()
        except:
            print "Process has stopped."
            sys.exit(1)

    def _createPidfile(self, pid):
        try:
            f = open(self.pidfile, "w")
            try: f.write(str(pid))
            finally: f.close()
        except OSError, e:
            sys.stderr.write(format_exc())
            sys.stderr.write("\n")
            sys.stderr.write("Failed to write to pid file, exiting now.\n")
            sys.exit(1)

    def alrmHandler(self, signum, frame):
        sys.exit(1)

    def termHandler(self, signum, frame):
        self.running = False
        self._stop()
        signal.signal(signal.SIGALRM, self.alrmHandler)
        signal.alarm(5)

    def run(self):
        sleep(1)

    def _stop(self):
        pass

    def start(self):
        if exists(self.pidfile):
            print "Process already exists, exiting now."
            sys.exit(1)
        from daemonize import become_daemon
        print "starting..."
        become_daemon(self.workdir)
        self._createPidfile(os.getpid())
        signal.signal(signal.SIGTERM, self.termHandler)
        try:
            self.run()
            #while self.running:
            #    try:
            #        self.run()
            #    except:
            #        pass
        finally:
            os.remove(self.pidfile)

    def stop(self):
        pid = self.pid
        sys.stdout.write("stopping.")
        sys.stdout.flush()
        os.kill(pid, signal.SIGTERM)
        while exists(self.pidfile):
            sys.stdout.write(".")
            sys.stdout.flush()
            sleep(0.5)
        sys.stdout.write("\n")

    def restart(self):
        if exists(self.pidfile):
            self.stop()
        self.start()

    def status(self):
        pid = self.pid
        if _checkAlive(pid):
            print 'Process is running at pid %s' % pid
        else:
            print 'Process has stopped'

    def main(self):
        if len(sys.argv) < 2:
            self.print_usage()
            sys.exit()
        cmd = sys.argv[1]
        if not cmd in ("start", "stop", "restart", "status"):
            self.print_usage()
            sys.exit()
        return getattr(self, cmd)()

    def print_usage(self):
        print "Usage: %s {start|stop|restart|status}"%(sys.argv[0],)


if __name__ == "__main__":
    initd = Initd()
    initd.main()
